package org.acm.seguin.uml.line; import java.awt.Dimension; import java.awt.LayoutManager; import java.awt.Point; import java.awt.Rectangle; import javax.swing.JPanel; /** * Panel that can be scaled and shifted * *@author Chris Seguin */ abstract class ScalablePanel extends JPanel { private double scale; private boolean inShapeChange; private int absoluteWidth = -1; private int absoluteHeight = -1; private boolean inScaling = false; private int absoluteX = -1; private int absoluteY = -1; /** * Constructor for the ScalablePanel object */ public ScalablePanel() { init(); } /** * Constructor for the ScalablePanel object * *@param doubleBuffered Description of Parameter */ public ScalablePanel(boolean doubleBuffered) { super(doubleBuffered); init(); } /** * Constructor for the ScalablePanel object * *@param layout Description of Parameter */ public ScalablePanel(LayoutManager layout) { super(layout); init(); } /** * Constructor for the ScalablePanel object * *@param layout Description of Parameter *@param doubleBuffered Description of Parameter */ public ScalablePanel(LayoutManager layout, boolean doubleBuffered) { super(layout, doubleBuffered); init(); } /** * Sets the Location attribute of the ScalablePanel object * *@param x The new Location value *@param y The new Location value */ public void setLocation(int x, int y) { if (inShapeChange) { super.setLocation(x, y); } else { inShapeChange = true; super.setLocation(scaleInteger(x), scaleInteger(y)); inShapeChange = false; } } /** * Sets the Location attribute of the ScalablePanel object * *@param pt The new Location value */ public void setLocation(Point pt) { if (inShapeChange) { super.setLocation(pt); } else { inShapeChange = true; super.setLocation(scaleInteger(pt.x), scaleInteger(pt.y)); inShapeChange = false; } } /** * Sets the Size attribute of the ScalablePanel object * *@param w The new Size value *@param h The new Size value */ public void setSize(int w, int h) { if (inShapeChange) { super.setSize(w, h); } else { inShapeChange = true; super.setSize(scaleInteger(w), scaleInteger(h)); inShapeChange = false; } } /** * Sets the Size attribute of the ScalablePanel object * *@param dim The new Size value */ public void setSize(Dimension dim) { if (inShapeChange) { super.setSize(dim); } else { inShapeChange = true; super.setSize(scaleInteger(dim.width), scaleInteger(dim.height)); inShapeChange = false; } } /** * Sets the Bounds attribute of the ScalablePanel object * *@param x The new Bounds value *@param y The new Bounds value *@param w The new Bounds value *@param h The new Bounds value */ public void setBounds(int x, int y, int w, int h) { if (inShapeChange) { super.setBounds(x, y, w, h); } else { inShapeChange = true; super.setBounds(scaleInteger(x), scaleInteger(y), scaleInteger(h), scaleInteger(h)); inShapeChange = false; } } /** * Sets the Bounds attribute of the ScalablePanel object * *@param rect The new Bounds value */ public void setBounds(Rectangle rect) { if (inShapeChange) { super.setBounds(rect); } else { inShapeChange = true; super.setBounds(scaleInteger(rect.x), scaleInteger(rect.y), scaleInteger(rect.width), scaleInteger(rect.height)); inShapeChange = false; } } /** * This method moves the class diagram around on the screen * *@param x the x coordinate *@param y the y coordinate */ public void shift(int x, int y) { Point pt = getLocation(); inShapeChange = true; setLocation(x + pt.x, y + pt.y); inShapeChange = false; } /** * Scales the image * *@param value the amount to scale */ public void scale(double value) { if (Math.abs(scale - value) > 0.001) { Rectangle rect = getUnscaledBounds(); scale = value; inScaling = true; setBounds(rect); inScaling = false; } } /** * Invokes old version of setLocation * *@param x Description of Parameter *@param y Description of Parameter */ public void move(int x, int y) { if (inShapeChange) { super.move(x, y); } else { inShapeChange = true; super.move(scaleInteger(x), scaleInteger(y)); inShapeChange = false; } } /** * Description of the Method * *@param w Description of Parameter *@param h Description of Parameter */ public void resize(int w, int h) { if (inShapeChange) { super.resize(w, h); } else { inShapeChange = true; super.resize(scaleInteger(w), scaleInteger(h)); inShapeChange = false; } } /** * Description of the Method * *@param dim Description of Parameter */ public void resize(Dimension dim) { if (inShapeChange) { super.resize(dim); } else { inShapeChange = true; super.resize(scaleInteger(dim.width), scaleInteger(dim.height)); inShapeChange = false; } } /** * Description of the Method * *@param x Description of Parameter *@param y Description of Parameter *@param w Description of Parameter *@param h Description of Parameter */ public void reshape(int x, int y, int w, int h) { if (inShapeChange) { super.reshape(x, y, w, h); } else { inShapeChange = true; super.reshape(scaleInteger(x), scaleInteger(y), scaleInteger(h), scaleInteger(h)); inShapeChange = false; } } /** * Return the scaling factor * *@return the scaling factor */ protected double getScale() { return scale; } /** * Scale the integer * *@param value the value to be converted *@return the scaled version */ protected int scaleInteger(int value) { return (int) Math.round(scale * value); } /** * Get the bounds without scaling factors * *@return the rectangle containing the boundaries */ private Rectangle getUnscaledBounds() { Rectangle rect = getBounds(); if (Math.abs(scale - 1.0) < 0.01) { absoluteX = rect.x; absoluteY = rect.y; absoluteWidth = rect.width; absoluteHeight = rect.height; } else { rect.x = getCoordinate(rect.x, absoluteX); rect.y = getCoordinate(rect.y, absoluteY); if (absoluteWidth == -1) { rect.width = unscaleInteger(rect.width); rect.height = unscaleInteger(rect.height); } else { rect.width = absoluteWidth; rect.height = absoluteHeight; } } return rect; } /** * Convert a coordinate or use an absolute coordinate * *@param value the input coordinate *@param absolute the absolute coordinate *@return the correct coordinate */ private int getCoordinate(int value, int absolute) { int scaled = unscaleInteger(value); if ((absolute >= 0) && (Math.abs(scaled - absolute) < 6)) { scaled = absolute; } return scaled; } /** * Inverse of the scaleInteger operation * *@param value the input value *@return the result of the unscape operation */ private int unscaleInteger(int value) { return (int) (value / scale); } /** * Initialize the valuse */ private void init() { inShapeChange = false; scale = 1.0; } }